package com.fw.application.controller;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fw.application.controller.base.BaseController;
import com.fw.common.AliComm;
import com.fw.common.IdXD;
import com.fw.constant.Constant;
import com.fw.enums.LogsModelEnum;
import com.fw.enums.LogsTypeEnum;
import com.fw.enums.OrderState;
import com.fw.mes.Result;
import com.fw.system.comm.service.DistrictService;
import com.fw.system.web.model.entity.*;
import com.fw.system.web.model.form.ReadyOrderForm;
import com.fw.system.web.model.form.ReadyOrderFormForm;
import com.fw.system.web.model.vo.AddrsVo;
import com.fw.system.web.service.*;
import com.fw.utils.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

import static com.fw.mes.ResultUtils.success;

/**
 * 竞猜Controller
 *
 * @author yanwei
 * @Date 2021-06-23
 */
@RestController
@RequestMapping("/guess")
@Api(tags = "竞猜相关")
@RequiredArgsConstructor
@Log4j2
public class FwGuessController implements BaseController {
    @Autowired
    private IFwDisappearFreedService disappearFreedService;
    private final IFwGuessService guessService;
    private final IFwUgJoinService ugJoinService;
    private final IFwUserService userService;
    private final IdXD idXD;
    private final IFwOrderService orderService;
    private final DistrictService districtService;
    private final IFwAddrsService addrsService;
    private final IFwSpuService spuService;
    private final IFwSkuService skuService;
    private final IFwParentOrderService parentOrderService;
    private final AliComm aliComm;
    private final IFwMoneysService moneysService;
    private final IFwShopService shopService;
    private final IFwUljoinService uljoinService;
    private final IFwLogsService logsService;


    /**
     * 查询竞猜列表
     */
    @GetMapping("/list")
    @ApiOperation("查询竞猜列表")
    public Result<Object> list(@RequestParam(defaultValue = "0") Integer pageNum,
                               @RequestParam(defaultValue = "10") Integer pageSize) {
        FwUser user = getDefaultUser();
        String userId = "";
        if (user != null) {
            userId = user.getId();
        }
        PageHelper.startPage(pageNum, pageSize);
        List<FwUgJoin> guessIdList = ugJoinService.list(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getUserId, userId)
                .eq(FwUgJoin::getIsValid, 1)
                .eq(FwUgJoin::getIsAuto, 0)
                .orderByDesc(FwUgJoin::getUpdateTime));
        for (FwUgJoin ug : guessIdList) {
            FwGuess guess = guessService.getById(ug.getGuessId());
            FwSpu spu = spuService.getById(guess.getSpuId());
            if ( spu != null) {
                ug.setSpuPhoto(spu.getLogo());
                ug.setSpuName(spu.getTitle());
                ug.setSpuDisappear(spu.getDisappear());
            }
            if (StringUtils.isEmpty(guess.getVictoryUserId())) {
                ug.setIsVictory("0");
            } else if (getUser().getId().equals(guess.getVictoryUserId())) {
                ug.setIsVictory("1");
            } else {
                ug.setIsVictory("2");
            }
        }
        PageInfo<FwUgJoin> pageInfo = new PageInfo<>(guessIdList);
        return success(pageInfo);
    }

    /**
     * 获取竞猜详细信息
     */
    @GetMapping(value = "/{guessId}")
    @ApiOperation("详情")
    public Result<FwGuess> getInfo(@PathVariable("guessId") String guessId, @RequestParam(defaultValue = "0") String isShare) {
        String userId = "";
        if ("0".equals(isShare)) {
            userId = getUser().getId();
        }

        FwGuess guess = guessService.getById(guessId);
        guess.setShareUrl(Constant.ShareUrl.GUESS_URL + "?key=sjpk&guessid=" + guess.getGuessId());
        guess.setUgList(ugJoinService.list(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guess.getGuessId())));
        guess.getUgList().forEach(ug -> {
            ug.setUser(userService.getById(ug.getUserId()));
            //是否胜利
            if (StringUtils.isEmpty(guess.getVictoryUserId())) {
                ug.setIsVictory("0");
            } else if (ug.getUserId().equals(guess.getVictoryUserId())) {
                ug.setIsVictory("1");
            } else {
                ug.setIsVictory("2");
            }
        });
        guess.setFwSpu(spuService.getById(guess.getSpuId()));
        guess.setFwSku(skuService.getById(guess.getSkuId()));
        guess.setIsHomeowner(guess.getCreateBy().equals(userId) ? 1 : 0);
        guess.setPkTime(guess.getPkTime() == null ? null : guess.getPkTime().plusSeconds(20));
        //是否有结果
        List<FwUgJoin> ugJoinList = ugJoinService.list(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guess.getGuessId())
                .eq(FwUgJoin::getIsValid, 1));
        int flag = 1;
        for (FwUgJoin ug : ugJoinList) {
            if (ug.getResult() == 0 || ug.getIsCover() == 1) {
                flag = 0;
                break;
            }
        }
        guess.setIsOver(flag);

        //结束时间
        guess.setOverTime(guess.getCreateTime().plusHours(2));
        guess.setUserId(userId);
        return success(guess);
    }

    /**
     * @Effect 精彩统计(统计订单参与人次 ， 及最近的几个用户头像)
     * @Author 姚
     * @Date 2021/6/21
     **/
    @GetMapping("/guessCount")
    @ApiOperation("Y:竞猜统计")
    public Result<Map<String, Object>> guessCount() {
        //人次
        int count = ugJoinService.count();
        //头像
        List<Object> userIdList = ugJoinService.listObjs(Wrappers.<FwUgJoin>lambdaQuery()
                .select(FwUgJoin::getUserId)
                .orderByDesc(FwUgJoin::getCreateTime)
                .last(" limit 10"));
        List<Object> imageList = userService.listObjs(Wrappers.<FwUser>lambdaQuery()
                .select(FwUser::getHeadImage)
                .in(FwUser::getId, userIdList));
        HashMap<String, Object> resultMap = new HashMap<>(4);
        resultMap.put("count", count);
        resultMap.put("list", imageList);
        return success(resultMap);
    }

    /**
     * 预订单
     */
    @PostMapping("/readyOrder")
    @ApiOperation("预订单")
    public Result<Object> readyOrder(@RequestBody ReadyOrderFormForm formForm) {
        List<ReadyOrderForm> formList = formForm.getFormList();
        //订单
        BigDecimal orderMoney = new BigDecimal(0);

        for (ReadyOrderForm form : formList) {
            FwSku fwSku = skuService.getById(form.getSkuId());
            if (fwSku == null) { return new Result<>().fail(1,"没有获取到相应商品规格"+form.getSkuId()); }
            //商品金额 * 数量
            orderMoney = orderMoney.add(fwSku.getSkuMoney().multiply(new BigDecimal(form.getNumber())));
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("orderMoney", orderMoney);
        resultMap.put("overAmount", orderMoney);//实付
        FwAddrs fwAddrs = addrsService.getOne(Wrappers.<FwAddrs>lambdaQuery().eq(FwAddrs::getUserId, getUser().getId())
                .eq(FwAddrs::getIsDefault, 1));
        AddrsVo addrsVo = new AddrsVo();
        if (fwAddrs != null) {
            BeanUtil.copyProperties(fwAddrs, addrsVo);
            addrsVo.setAreaName(districtService.codeConversionName(fwAddrs.getArea()));
            addrsVo.setCityName(districtService.codeConversionName(fwAddrs.getCity()));
            addrsVo.setProvinceName(districtService.codeConversionName(fwAddrs.getProvince()));
        }
        resultMap.put("defaultAddr", addrsVo);
        return success(resultMap);
    }

    /**
     * 提交竞猜订单
     */
    @PostMapping("/commitGuess")
    @ApiOperation("提交竞猜订单")
    public Result<Object> commitGuess(@RequestBody ReadyOrderFormForm formForm) {
        String userId = getUser().getId();
        List<FwShop> shopList = shopService.list(Wrappers.<FwShop>lambdaQuery().eq(FwShop::getUserId, userId));
        FwGuess guess = guessService.getById(formForm.getGuessId());
        //判断能不能进房间
        if (guess != null) {
            int count = ugJoinService.count(Wrappers.<FwUgJoin>lambdaQuery()
                    .eq(FwUgJoin::getGuessId, guess.getGuessId())
                    .eq(FwUgJoin::getIsValid, 1));
            if (count >= guess.getPeopleNumber())
                return new Result<>().fail(1, "房间人数已满");
        }
        //生成订单
        List<ReadyOrderForm> formList = formForm.getFormList();
        //订单
        BigDecimal orderMoney = new BigDecimal(0);

        //大订单
        FwParentOrder parentOrder = new FwParentOrder();
        parentOrder.setParentOrderId(idXD.nextId());
        parentOrder.setUserId(getUser().getId());
        parentOrder.setState(OrderState.PENDING_PAYMENT.getCode());
        parentOrder.setCreateTime(LocalDateTime.now());

        ArrayList<FwOrder> orderList = new ArrayList<>();
        for (ReadyOrderForm form : formList) {
            FwSku fwSku = skuService.getById(form.getSkuId());
            FwSpu fwSpu = spuService.getById(fwSku.getSpuId());
            if (shopList != null && shopList.size() > 0) {
                for (FwShop shop : shopList) {
                    if (fwSpu.getShopId().equals(shop.getId())) {
                        return new Result<>().fail(1, "不能购买自己商铺的产品: " + fwSpu.getTitle());
                    }
                }
            }
            //判断库存是否充足
            if (fwSku.getSkuBalance() < form.getNumber()) {
                return new Result<>().fail(100, fwSpu.getTitle() + fwSku.getSkuName() + "库存不足");
            }

            //小订单，商品金额
            BigDecimal smallOrderMoney = fwSku.getSkuMoney().multiply(new BigDecimal(form.getNumber()));

            //商品金额 * 数量
            orderMoney = orderMoney.add(smallOrderMoney);

            //生成临时地址Id
            FwAddrs orderAddr = addrsService.getById(form.getAddrId());
            orderAddr.setId(idXD.nextId());
            orderAddr.setUserId("");
            addrsService.save(orderAddr);

            //订单
            FwOrder order = new FwOrder();
            order.setId(idXD.nextId());
            order.setUserId(parentOrder.getUserId());
            order.setIsQuiz(1);
            order.setTotalPrice(smallOrderMoney);//实付
            order.setTotalFullPrice(smallOrderMoney);
            order.setStatus(OrderState.PENDING_PAYMENT.getCode());
            order.setShopId(fwSpu.getShopId());
            order.setCreateTime(LocalDateTime.now());
            order.setParentOrderId(parentOrder.getParentOrderId());
            order.setSpuId(fwSpu.getId());
            order.setSkuId(fwSku.getId());
            order.setSpuNumber(form.getNumber());
            order.setShopping(fwSpu.getShipping());
            order.setAddrId(orderAddr.getId());
            order.setFullDiscount(new BigDecimal(0));
            order.setRemoveFlag(1);//竞猜完成后，胜利者有效
            orderService.save(order);
            orderList.add(order);
        }
        parentOrder.setOrderList(orderList);
        parentOrder.setParentOrderMoney(orderMoney);
        parentOrder.setTotalFullPrice(orderMoney);
        parentOrder.setShopping(new BigDecimal(0));
        parentOrder.setFullDiscount(new BigDecimal(0));
        parentOrderService.save(parentOrder);

        //塞进房间（创建竞猜订单）
        if (guess == null) {
            //房主,创建房间
            guess = new FwGuess()
                    .setGuessId(idXD.nextId())
                    .setSpuId(parentOrder.getOrderList().get(0).getSpuId())
                    .setSkuId(parentOrder.getOrderList().get(0).getSkuId())
                    .setBuyNumber(parentOrder.getOrderList().get(0).getSpuNumber())
                    .setPeopleNumber(formForm.getPeopleNumber())
                    .setCreateBy(userId)
                    .setCreateTime(LocalDateTime.now());
            guessService.save(guess);

            //减库存
            skuService.subtractBalance(guess.getSkuId(), guess.getBuyNumber());
            //加销量
            spuService.addTops(guess.getSpuId(), guess.getBuyNumber());
        }
        //把人塞进房间
        ugJoinService.save(new FwUgJoin().setUgId(idXD.nextId())
                .setUserId(userId)
                .setGuessId(guess.getGuessId())
                .setResult(0)
                .setOrderId(parentOrder.getOrderList().get(0).getId())
                .setIsAuto(0)
                .setIsValid(0)
                .setIsCover(0)
                .setCreateTime(LocalDateTime.now()));
        parentOrder.setGuessId(guess.getGuessId());
        return success(parentOrder);
    }

    /**
     * @Effect 用户猜拳PK（时间到了）
     * @Author 姚
     * @Date 2021/6/22
     **/
    @GetMapping("/userPK/{guessId}/{result}")
    @ApiOperation("猜拳PK(用户确认出拳，自动PK)")
    public Result<Object> userPK(@PathVariable String guessId, @PathVariable Integer result) {
        FwGuess guess = guessService.getById(guessId);
        if (guess == null) {
            return new Result<>().fail(1, "房间不存在");
        }
        if (guess.getVictoryUserId() != null) {
            return new Result<>().fail(3, "房间竞猜已结束");
        }
        if (result < 1 || result > 3) {
            return new Result<>().fail(2, "出拳异常");
        }
        FwUgJoin ugJoin = ugJoinService.getOne(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guess.getGuessId())
                .eq(FwUgJoin::getUserId, getUser().getId()));
        if (ugJoin.getResult() != 0 && ugJoin.getIsCover() == 0) {
//            return new Result<>().fail(4,"请勿重复出拳");
            return success();
        }
        ugJoin.setResult(result);
        ugJoin.setIsCover(0);
        ugJoin.setUpdateTime(LocalDateTime.now());
        ugJoinService.updateById(ugJoin);

        int count = ugJoinService.count(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guess.getGuessId())
                .eq(FwUgJoin::getIsCover, 0)
                .ne(FwUgJoin::getResult, 0));
        if (count == guess.getPeopleNumber() && StringUtils.isBlank(guess.getVictoryUserId())) {
            //人齐了，还未产生胜利者，猜拳
            guessPk(guess.getGuessId());
        }
        return success();
    }

    /**
     * 竞猜
     */
    @GetMapping("/guessPk/{guessId}")
    @ApiOperation("猜拳PK(倒计时结束，强制PK)")
    public synchronized Result<Object> guessPk(@PathVariable String guessId) {
        int autoNum = 0;
        int autoIndex = 0;
        FwGuess guess = guessService.getById(guessId);

        if ( StringUtils.isNotBlank(guess.getVictoryUserId()) ) {
            //已经存在胜利者
            return new Result<>().fail(1, "本次竞猜已结束");
        }

        List<FwUgJoin> ugJoinList = ugJoinService.list(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guess.getGuessId())
                .eq(FwUgJoin::getIsValid, 1)
                .orderByAsc(FwUgJoin::getCreateTime));

        if (guess.getPeopleNumber() != ugJoinList.size()) {
            return new Result<>().fail(1, "房间人数异常");
        }

        //统计机器人数量
        Random random = new Random();
        int index = 0;
        for (FwUgJoin ug : ugJoinList) {
            //result赋值
            if (ug.getResult() == 0) {
                ug.setResult(random.nextInt(4));
                ug.setOldResult(ug.getResult());
            }

            //将数据复制到，oldResult
            ugJoinService.update(Wrappers.<FwUgJoin>lambdaUpdate()
                    .set(FwUgJoin::getOldResult, ug.getResult())
                    .set(FwUgJoin::getResult, ug.getResult())
                    .set(FwUgJoin::getUpdateTime, LocalDateTime.now())
                    .eq(FwUgJoin::getUgId, ug.getUgId()));

            if (ug.getIsAuto() == 1) {
                autoNum++;
                autoIndex = index;
            }
            index++;


        }

        if (guess.getPeopleNumber() != ugJoinList.size()) {
            return new Result<>().fail(1, "房间人数异常");
        }

        int pk = -1;
        //全都是真人的情况下

        int int1 = ugJoinList.get(0).getResult();
        int int2 = ugJoinList.get(1).getResult();
        int int3 = 0;
        if (guess.getPeopleNumber() == 3) {
            int3 = ugJoinList.get(2).getResult();
        }
        if (autoNum == 0) {
            pk = pk(int1, int2, int3, guess.getPeopleNumber()) - 1;
        } else if (autoNum == 2) {
            int autoResult = 1;
            while (autoResult == ugJoinList.get(0).getResult()) {
                autoResult = random.nextInt(4);
            }
            ugJoinList.get(1).setResult(autoResult);
            ugJoinList.get(1).setOldResult(ugJoinList.get(1).getResult());
            ugJoinList.get(1).setUpdateTime(LocalDateTime.now());
            ugJoinList.get(2).setResult(autoResult);
            ugJoinList.get(2).setOldResult(ugJoinList.get(2).getResult());
            ugJoinList.get(2).setUpdateTime(LocalDateTime.now());
            ugJoinService.updateById(ugJoinList.get(1));
            ugJoinService.updateById(ugJoinList.get(2));
            pk = 0;
        } else {
            if (guess.getPeopleNumber() == 2) {
                //两人中，一人为机器人
                if (ugJoinList.get(0).getResult() == 3) {
                    ugJoinList.get(1).setResult(1);
                } else {
                    ugJoinList.get(1).setResult(ugJoinList.get(0).getResult() + 1);
                }
                ugJoinList.get(1).setUpdateTime(LocalDateTime.now());
                ugJoinList.get(1).setOldResult(ugJoinList.get(1).getResult());
                ugJoinService.updateById(ugJoinList.get(1));
                pk = 0;
            } else {
                //三人一人为机器人
                if (random.nextInt(2) == 1) {
                    ugJoinList.get(autoIndex).setResult(ugJoinList.get(0).getResult());
                    ugJoinList.get(autoIndex).setOldResult(ugJoinList.get(0).getResult());
                    ugJoinList.get(autoIndex).setUpdateTime(LocalDateTime.now());
                    ugJoinService.updateById(ugJoinList.get(autoIndex));
                } else {
                    if (autoIndex == 1) {
                        ugJoinList.get(autoIndex).setResult(ugJoinList.get(2).getResult());
                        ugJoinList.get(autoIndex).setOldResult(ugJoinList.get(2).getResult());
                    } else {
                        ugJoinList.get(autoIndex).setResult(ugJoinList.get(1).getResult());
                        ugJoinList.get(autoIndex).setOldResult(ugJoinList.get(1).getResult());
                    }
                }
                pk = pk(int1, int2, int3, guess.getPeopleNumber()) - 1;
            }
        }
        if (pk != -1) {
            //产生了胜利者
            guess.setVictoryUserId(ugJoinList.get(pk).getUserId());
            guessService.updateById(guess);
            //结束后的操作
            try {
                victoryAfter(guess, ugJoinList);
            } catch (IllegalArgumentException e) {
                //AlipayFundTransToaccountTransferResponse
                JSONObject jsonObject = JSON.parseObject(e.getMessage());
                String msg = jsonObject.getJSONObject("alipay_fund_trans_toaccount_transfer_response").getString("sub_msg");
                return success().fail(1001, msg);
            } catch (AlipayApiException e) {
                return success().fail(1001, e.getMessage());
            }
        } else {
            //平局
            ugJoinService.update(Wrappers.<FwUgJoin>lambdaUpdate()
                    .set(FwUgJoin::getIsCover, 1)
                    .eq(FwUgJoin::getIsValid, 1)
                    .eq(FwUgJoin::getGuessId, guess.getGuessId()));
        }
        //更新PK时间
        guessService.update(Wrappers.<FwGuess>lambdaUpdate()
                .set(FwGuess::getPkTime, LocalDateTime.now())
                .eq(FwGuess::getGuessId, guess.getGuessId()));
        return success();
    }

    /**
     * 全是用户的情况下 猜拳
     */
    int pk(int int1, int int2, int int3, int peopleNumber) {
        if (peopleNumber == 2) {
            int abs = Math.abs(int1 - int2);
            if (abs == 0) {
                return 0;
            } else if (abs == 1) {
                //相邻 12 ， 23 ，小的赢
                if (int1 < int2) {
                    return 1;
                } else {
                    return 2;
                }
            } else if (abs == 2) {
                //不相邻 13 ， 大得赢
                if (int1 > int2) {
                    return 1;
                } else {
                    return 2;
                }
            }
        } else if (peopleNumber == 3) {
            if (int1 == int2 && int1 == int3) {
                return 0;
            }
            if (int1 != int2 && int1 != int3 && int2 != int3) {
                return 0;
            }
            if (int1 == int2) {
                return 3;
            }
            if (int1 == int3) {
                return 2;
            }
            return 1;
        }
        return 0;
    }

    /**
     * 竞猜是否结束
     */
    @ApiOperation("竞猜是否有结果，包含平局")
    @GetMapping(value = "/isOver/{guessId}/{flag}")
    public Result<Object> isOver(@PathVariable("guessId") String guessId, @PathVariable("flag") String flag) {
        FwGuess guess = guessService.getById(guessId);
        String userId = getUser().getId();
        if (guess == null) {
            return new Result<>().fail(1, "房间不存在");
        }
        List<FwUgJoin> ugJoinList = ugJoinService.list(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guess.getGuessId())
                .eq(FwUgJoin::getIsValid, 1));
        //竞猜结束（输/赢），需要出拳为1； 其他为零
        int isOver = 0;
        for (FwUgJoin ug : ugJoinList) {
            if (userId.equals(ug.getUserId()) && (ug.getResult() == 0 || ug.getIsCover() == 1)) {
                //自己需要出拳
                isOver = 1;
                break;
            }
        }
        //是否结束
        if (StringUtils.isNotEmpty(guess.getVictoryUserId())) {
            //竞猜已结束
            isOver = 0;
        }
        HashMap<String, String> resultMap = new HashMap<>();
        resultMap.put("isOver", isOver + "");
        resultMap.put("flag", flag);
        return success(resultMap);
    }

    /**
     * 添加机器人
     */
    @ApiOperation("添加机器人")
    @GetMapping(value = "/joinAuto/{guessId}")
    public Result<Object> joinAuto(@PathVariable("guessId") String guessId) {
        FwGuess guess = guessService.getById(guessId);
        if (guess == null) {
            return new Result<>().fail(1, "房间不存在");
        }
        List<FwUgJoin> ugJoinList = ugJoinService.list(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getIsValid, 1)
                .eq(FwUgJoin::getGuessId, guess.getGuessId()));
        List<Object> userIdList = ugJoinService.listObjs(Wrappers.<FwUgJoin>lambdaQuery()
                .select(FwUgJoin::getUserId)
                .eq(FwUgJoin::getIsValid, 1)
                .eq(FwUgJoin::getGuessId, guess.getGuessId()));
        if (guess.getPeopleNumber() > ugJoinList.size()) {
            int count = guess.getPeopleNumber() - ugJoinList.size();
            while (count > 0) {
                FwUser randUser = userService.getOne(Wrappers.<FwUser>lambdaQuery()
                        .notIn(FwUser::getId, userIdList)
                        .last("order by RAND() "));
                //把人塞进房间
                Random random = new Random();
                ugJoinService.save(new FwUgJoin().setUgId(idXD.nextId())
                        .setUserId(randUser.getId())
                        .setGuessId(guess.getGuessId())
                        .setResult(random.nextInt(4))
                        .setOrderId("")
                        .setIsAuto(1)
                        .setIsValid(1)
                        .setIsCover(0)
                        .setCreateTime(LocalDateTime.now()));
                count--;
            }
        }
        //更新PK时间
        guessService.update(Wrappers.<FwGuess>lambdaUpdate()
                .set(FwGuess::getPkTime, LocalDateTime.now())
                .eq(FwGuess::getGuessId, guess.getGuessId()));
        return success();
    }


    /**
     * 支付结束修改竞猜订单状态为有效，人数满了退款
     */
    @ApiOperation("测试用的，别调-支付结束修改竞猜订单状态为有效，人数满了退款")
    @PostMapping("/payAfter")
    public void payAfter(String orderId, String userId) {
        log.info("竞猜订单支付完成，订单号为：" + orderId);
        FwUgJoin ugJoin = ugJoinService.getOne(Wrappers.<FwUgJoin>lambdaQuery().eq(FwUgJoin::getOrderId, orderId));
        if (ugJoin == null) {
            log.info("未获取到订单号的数据，订单号：" + orderId);
            return;
        }
        FwGuess guess = guessService.getById(ugJoin.getGuessId());
        if (comeIn(ugJoin.getGuessId(), userId)) {
            log.info("真实进入房间订单号：" + orderId);
            ugJoin.setIsValid(1);
            ugJoin.setUpdateTime(LocalDateTime.now());
            ugJoinService.updateById(ugJoin);
            int count = guessService.count(Wrappers.<FwGuess>lambdaQuery().eq(FwGuess::getGuessId, ugJoin.getGuessId()));
            if (count == guess.getPeopleNumber()) {
                guess.setPkTime(LocalDateTime.now());
                guess.updateById();
            }
            return;
        }
        log.info("退款订单号：" + orderId);
        FwOrder order = orderService.getById(ugJoin.getOrderId());
        FwUser user = userService.getById(order.getUserId());
        try {
            aliComm.aliTransfer(user.getAliPhone(), order.getTotalPrice(), user.getAliUserName());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
    }

    /**
     * 是否可以进入
     */
    @GetMapping("/isComeIn/{guessId}")
    @ApiOperation("是否可以进入")
    public Result<Object> isComeIn(@PathVariable String guessId) {
        return success(comeIn(guessId, getUser().getId()));
    }

    /**
     * 是否可以进入
     */
    public boolean comeIn(String guessId, String userId) {
        FwGuess guess = guessService.getById(guessId);
        if (guess == null || !StringUtils.isEmpty(guess.getNewGuessId())
                || !StringUtils.isEmpty(guess.getVictoryUserId())) {
            return false;
        }
        List<FwUgJoin> list = ugJoinService.list(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guess.getGuessId())
                .eq(FwUgJoin::getIsValid, 1));
        for (FwUgJoin ug : list) {
            if (userId.equals(ug.getUserId())) {
                return false;
            }
        }
        return guess.getPeopleNumber() > list.size();
    }

    /**
     * 房间人员
     */
    @GetMapping("/guessPeoples/{guessId}/{flag}")
    @ApiOperation("房间人员")
    public Result<Map<String, Object>> guessPeoples(@PathVariable String guessId, @PathVariable String flag) {
        List<Object> userIds = ugJoinService.listObjs(Wrappers.<FwUgJoin>lambdaQuery()
                .select(FwUgJoin::getUserId)
                .eq(FwUgJoin::getGuessId, guessId)
                .eq(FwUgJoin::getIsValid, 1));
        List<FwUser> userList = userService.list(Wrappers.<FwUser>lambdaQuery()
                .in(FwUser::getId, userIds));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("list", userList);
        resultMap.put("flag", flag);
        return success(resultMap);
    }

    /**
     * 匹配
     */
    @GetMapping("/math/{guessId}")
    @ApiOperation("匹配")
    public Result<Object> math(@PathVariable String guessId) {
        /* 需要匹配房间的人数 */
        int mathPeopleNumber = 2;
        FwGuess myGuess = guessService.getById(guessId);
        int count = ugJoinService.count(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, guessId)
                .eq(FwUgJoin::getIsValid, 1));
        //确认房间人数
        if (myGuess.getPeopleNumber() == count) {
            return new Result<>().fail(1, "人数已满");
        } else if (count == 2) {
            mathPeopleNumber = 1;
        } else if (count == 1) {
            if (myGuess.getPeopleNumber() == 2) {
                mathPeopleNumber = 1;
            }
        }

        //得到一个可匹配的房间
        FwGuess mathGuess = guessService.getOne(Wrappers.<FwGuess>lambdaQuery()
                .eq(FwGuess::getSkuId, myGuess.getSkuId())
                .eq(FwGuess::getBuyNumber, myGuess.getBuyNumber())
                .eq(FwGuess::getPeopleNumber, myGuess.getPeopleNumber())
                .ne(FwGuess::getGuessId, myGuess.getGuessId())
                .eq(FwGuess::getIsMatch, 1)
                .exists("SELECT 1 FROM (" +
                        "SELECT guess_id,count(0) AS num FROM fw_ug_join ug " +
                        "WHERE guess_id = ug.guess_id AND is_valid = 1 GROUP BY guess_id " +
                        "HAVING num = 1 OR num = " + mathPeopleNumber +
                        ") existsTab " +
                        "WHERE existsTab.guess_id = fw_guess.guess_id")
                .notExists("SELECT 1 FROM fw_ug_join ug WHERE fw_guess.guess_id = ug.guess_id AND ug.user_id in " +
                        "(SELECT user_id FROM fw_ug_join WHERE guess_id = '" + myGuess.getGuessId() + "')"));
        //未匹配到房间， 将自己的房间标记待匹配
        if (mathGuess == null) {
            guessService.update(Wrappers.<FwGuess>lambdaUpdate()
                    .set(FwGuess::getIsMatch, 1)
                    .set(FwGuess::getUpdateTime, LocalDateTime.now())
                    .eq(FwGuess::getGuessId, myGuess.getGuessId()));
            return success(myGuess.getGuessId());
        }
        int mathCount = ugJoinService.count(Wrappers.<FwUgJoin>lambdaQuery()
                .eq(FwUgJoin::getGuessId, mathGuess.getGuessId())
                .eq(FwUgJoin::getIsValid, 1));

        //房间变更
        ugJoinService.update(Wrappers.<FwUgJoin>lambdaUpdate()
                .set(FwUgJoin::getGuessId, mathGuess.getGuessId())
                .set(FwUgJoin::getUpdateTime, LocalDateTime.now())
                .eq(FwUgJoin::getGuessId, myGuess.getGuessId()));
        guessService.removeById(myGuess.getGuessId());
        if (mathGuess.getPeopleNumber() <= count + mathCount) {
            guessService.update(Wrappers.<FwGuess>lambdaUpdate()
                    .set(FwGuess::getIsMatch, 0)
                    .eq(FwGuess::getGuessId, mathGuess.getGuessId()));
        }
        return success(mathGuess.getGuessId());
    }


    /**
     * 胜利之后，送消证，红包，积分兑换
     */
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void victoryAfter(FwGuess guess, List<FwUgJoin> ugJoinList) throws AlipayApiException {
        //给商户送消证，让利的三分之一
        FwSpu spu = spuService.getById(guess.getSpuId());
        FwShop shop = shopService.getById(spu.getShopId());
        BigDecimal shopDisappear = spu.getPrice().divide(new BigDecimal(3), 3, BigDecimal.ROUND_DOWN);
        //moneysService.disappearReturnParent(shop.getUserId(), null, spu.getPrice().divide(new BigDecimal(3), 3, BigDecimal.ROUND_DOWN), "竞猜出售", null);
        moneysService.shopDisappearReturn(shop,shopDisappear,shopDisappear.toString(),"用户竞猜消费商户获取消证{}");
        FwOrder victoryOrder = null;

        for (FwUgJoin ug : ugJoinList) {
            if (ug.getUserId().equals(guess.getVictoryUserId())) {
                //胜利者的产品，上级得消证
                orderService.update(Wrappers.<FwOrder>lambdaUpdate()
                        .set(FwOrder::getRemoveFlag, 0)
                        .eq(FwOrder::getId, ug.getOrderId()));
                victoryOrder = orderService.getById(ug.getOrderId());
                moneysService.disappearReturn(ug.getUserId(), victoryOrder.getTotalPrice(), "竞猜送消证");
            } else {
                //是机器人跳过
                if (ug.getIsAuto() == 1) {
                    break;
                }
                //失败者得红包，上级兑换积分
                FwOrder order = orderService.getById(ug.getOrderId());
                FwUser user = userService.getById(order.getUserId());
                //红包是利润的60%
                BigDecimal redBag = spu.getPrice().multiply(BigDecimal.valueOf(order.getSpuNumber())).multiply(BigDecimal.valueOf(0.6));
                //三人间，红包减半，两人分
                if (guess.getPeopleNumber() == 3) {
                    redBag = redBag.divide(BigDecimal.valueOf(2), 2, BigDecimal.ROUND_DOWN);
                }
                //本金 + 红包 5%手续费
                BigDecimal refundAmount = order.getTotalPrice().add(redBag).multiply(BigDecimal.valueOf(0.95)).setScale(2, BigDecimal.ROUND_DOWN);
                //发红包
                log.info("发红包：" + refundAmount + "\t\t给-》" + user.getUserName());
                aliComm.aliTransfer(user.getAliPhone(), refundAmount, user.getAliUserName());
                log.info("发红包结束：" + refundAmount + "\t\t给-》" + user.getUserName());
                //更新红包数据
                ugJoinService.update(Wrappers.<FwUgJoin>lambdaUpdate()
                        .set(FwUgJoin::getRedBag, refundAmount)
                        .eq(FwUgJoin::getGuessId, guess.getGuessId())
                        .eq(FwUgJoin::getUserId, user.getId()));

                //消证兑换
                if (StringUtils.isNotEmpty(user.getParentId())) {
                    //上级的
                    BigDecimal integral = redBag.divide(BigDecimal.valueOf(10), 3, BigDecimal.ROUND_DOWN);
                    FwMoneys moneys = moneysService.getOne(Wrappers.<FwMoneys>lambdaQuery().eq(FwMoneys::getUserId, user.getParentId()));
                    FwUser parent = userService.getById(user.getParentId());

                    //获取用户所有身份数据,判断用户是否已经拥有vip身份
                    FwUljoin uljoin = uljoinService.getOne(Wrappers.<FwUljoin>lambdaQuery()
                            .eq(FwUljoin::getUserId, user.getParentId())
                            .eq(FwUljoin::getIsUse, 1));
                    if (moneys.getDisappear().compareTo(integral) > -1 && uljoin != null) {
                        //减消证，加积分
                        moneys.setDisappear(moneys.getDisappear().subtract(integral));
                        moneys.setIntegral(moneys.getIntegral().add(integral));
                        moneys.updateById();
                        //新增该用户的积分增加记录
                        logsService.saveLogs(user.getId(), parent.getId(), LogsTypeEnum.INTEGRAL_SPEED.getTypeName(),
                                LogsModelEnum.INTEGRAL_MODEL.getModelName(), "竞猜加速", integral.toString());
                        //新增该用户的消证加速记录
                        logsService.saveLogs(user.getId(), parent.getId(), LogsTypeEnum.INTEGRAL_SPEED.getTypeName(),
                                LogsModelEnum.DISAPPEAR_MODEL.getModelName(), "竞猜加速", integral.toString());
                        disappearFreedService.createFreed(integral,1,user.getId(),StringUtils.format("{}消证兑换积分",moneys.getDisappear()));
                    }

                    //其他人的
                    integralToUser(parent.getParentId(), integral.divide(BigDecimal.valueOf(2), 3, BigDecimal.ROUND_DOWN), 2, user.getId());
                }
            }
        }
    }

    /**
     * @param userId   用户ID
     * @param integral 多少积分
     * @param count    多少级内无条件反
     * @Effect 用户积分加速(递归上级)
     * @Author 姚
     * @Date 2021/7/6
     **/
    @Transactional(rollbackFor = Exception.class)
    public void integralToUser(String userId, BigDecimal integral, int count, String user_id) {
        if (integral.compareTo(BigDecimal.valueOf(0.001)) < 0) {
            return;
        }
        FwMoneys moneys = moneysService.getOne(Wrappers.<FwMoneys>lambdaQuery().eq(FwMoneys::getUserId, userId));
        FwUser user = userService.getById(userId);
        //用户为空，上个人无上级
        if (user == null) {
            return;
        }
        //获取用户所有身份数据,判断用户是否已经拥有vip身份
        FwUljoin uljoin = uljoinService.getOne(Wrappers.<FwUljoin>lambdaQuery()
                .eq(FwUljoin::getUserId, user.getId())
                .eq(FwUljoin::getIsUse, 1));

        //消证不足以兑换
        boolean flag = true;
        if (uljoin == null)
            flag = false;
        if (count < 0 && !user.getDisappearIsMore().equals(1))
            flag = false;
        if (moneys.getDisappear().compareTo(integral) < 0) {
            flag = false;
        }
        count--;
        if (flag) {
            //满足条件，进行积分加速
            //减消证，加积分
            moneys.setDisappear(moneys.getDisappear().subtract(integral));
            moneys.setIntegral(moneys.getIntegral().add(integral));
            moneys.updateById();
            //新增该用户的积分增加记录
            logsService.saveLogs(user_id, userId, LogsTypeEnum.INTEGRAL_SPEED.getTypeName(),
                    LogsModelEnum.INTEGRAL_MODEL.getModelName(), "竞猜加速", integral.toString());
            //新增该用户的消证加速记录
            logsService.saveLogs(user_id, userId, LogsTypeEnum.INTEGRAL_SPEED.getTypeName(),
                    LogsModelEnum.DISAPPEAR_MODEL.getModelName(), "竞猜加速", integral.toString());
            disappearFreedService.createFreed(integral,1,userId,StringUtils.format("{}消证兑换积分",moneys.getDisappear()));
        }
        integralToUser(user.getParentId(), integral.divide(BigDecimal.valueOf(2), 3, BigDecimal.ROUND_DOWN), count, user_id);
    }

}
